<template>
  <a-form-model
    class="c-form"
    :model="form"
    :layout="layout"
    :selfUpdate="true"
    :ref="refs"
    :rules="rules || defaultRules"
    :label-col="showLabel ? labelCol : { span: 0 }"
    :wrapper-col="showLabel ? wrapperCol : { span: 24 }"
    :colon="colon"
    @validate="validate"
  >
    <template v-for="item in data">
      <a-form-model-item
        v-if="!item.hidden"
        :label="showLabel && !item.labelSlot ? item.label : undefined"
        :colon="
          item.colon !== undefined
            ? item.colon
            : item.type === 'submit'
            ? false
            : colon
        "
        :key="item.prop"
        :prop="item.prop"
        :wrapperCol="
          item.wrapperCol
            ? item.wrapperCol
            : showLabel
            ? wrapperCol
            : { span: 24 }
        "
      >
        <span slot="label">
          <slot :name="item.labelSlot" />
        </span>
        <!-- change传递给父级，用于校验 -->
        <slot
          :name="item.slot"
          :data="item"
          :change="validateField"
          v-if="item.slot"
        />
        <template v-else>
          <a-select
            v-model="form[item.prop]"
            optionFilterProp="children"
            :showSearch="item.showSearch == 'false' ? false : true"
            :placeholder="item.placeholder || '请选择' + item.label"
            :mode="item.mode || 'default'"
            :disabled="item.disabled"
            :allowClear="item.clear"
            v-if="item.type === 'select'"
            option-label-prop="label"
            :dropdownMatchSelectWidth="
              'dropdownMatchSelectWidth' in item
                ? item.dropdownMatchSelectWidth
                : true
            "
            @change="
              (val, option) => {
                selectChange(val, option, item.prop);
              }
            "
          >
            <template v-for="i in item.typeData">
              <a-select-option
                :key="
                  i[item.replaceFields && item.replaceFields.value] || i.value
                "
                :label="
                  item.selectOptionLabel
                    ? item.selectOptionLabel(i)
                    : item.selectLabel
                    ? item.selectLabel(i)
                    : i[item.replaceFields && item.replaceFields.label] ||
                      i.label
                "
              >
                <span v-if="item.selectOptionLabel">
                  {{ item.selectOptionLabel(i) }}
                </span>
                <span v-else>
                  {{
                    i[item.replaceFields && item.replaceFields.label] || i.label
                  }}
                </span>
              </a-select-option>
            </template>
          </a-select>
          <a-cascader
            v-model="form[item.prop]"
            :options="item.typeData"
            :field-names="
              item.replaceFields || {
                label: 'label',
                value: 'value',
                children: 'children'
              }
            "
            expand-trigger="hover"
            :placeholder="item.placeholder || '请选择' + item.label"
            @change="cascaderChange"
            v-else-if="item.type === 'cascader'"
          />
          <a-tree
            :checkedKeys="form[item.prop]"
            :disabled="item.disabled"
            :defaultExpandedKeys="form[item.prop]"
            :tree-data="item.typeData"
            checkable
            :replaceFields="
              item.replaceFields ? item.replaceFields : replaceFields
            "
            @check="onTreeCheck"
            v-else-if="item.type === 'tree' && item.typeData.length !== 0"
          ></a-tree>
          <a-textarea
            v-model="form[item.prop]"
            :placeholder="item.placeholder || '请输入' + item.label"
            :disabled="item.disabled"
            v-else-if="item.type === 'textarea'"
          ></a-textarea>
          <a-radio-group
            v-model="form[item.prop]"
            :disabled="item.disabled"
            @change="radioChange"
            v-else-if="item.type === 'radio'"
          >
            <a-radio :value="i.value" v-for="i in item.typeData" :key="i.value">
              {{ i.label }}
            </a-radio>
          </a-radio-group>
          <a-switch
            v-else-if="item.type === 'switch'"
            v-model="form[item.prop]"
          ></a-switch>
          <a-input-password
            v-model="form[item.prop]"
            :disabled="item.disabled"
            :placeholder="item.placeholder || '请输入' + item.label"
            v-else-if="item.type === 'password'"
            @pressEnter="pressEnter"
          >
            <template v-slot:prefix v-if="item.prefix">
              <c-icon :type="item.prefix" size="14" />
            </template>
          </a-input-password>
          <a-input-number
            v-model.trim="form[item.prop]"
            :disabled="item.disabled"
            :placeholder="item.placeholder || '请输入' + item.label"
            v-else-if="item.type === 'number'"
            :precision="'precision' in item ? item.precision : undefined"
            :max="item.max"
            :min="item.min"
          >
          </a-input-number>
          <c-button
            v-else-if="item.type === 'submit'"
            class="sumbit-btn"
            :width="item.submitWidth"
            :disabled="item.disabled"
            block
            type="primary"
            @click="submit"
            :loading="submitLoading"
            >{{ item.submitText || "提交" }}</c-button
          >
          <a-input
            v-model.trim="form[item.prop]"
            :disabled="item.disabled"
            :placeholder="item.placeholder || '请输入' + item.label"
            v-if="item.type === 'input' || !item.type"
            :type="item.inputType"
          >
            <template v-slot:prefix v-if="item.prefix">
              <c-icon :type="item.prefix" size="14" />
            </template>
            <template v-slot:suffix v-if="item.suffix">
              <c-icon :type="item.suffix" size="14" />
            </template>
          </a-input>
          <span v-if="item.type === 'text'">{{ form[item.prop] }}</span>
        </template>
      </a-form-model-item>
    </template>
  </a-form-model>
</template>

<script>
export default {
  props: {
    // 用于渲染的数据
    data: {
      type: Array,
      default: () => {
        return [];
      }
    },
    // 布局类型
    layout: {
      type: String,
      default: "horizontal"
    },
    // 校验规则
    rules: {
      type: Object
    },
    value: {
      type: Object
    },
    refs: {
      type: String,
      default: "formModel"
    },
    // 是否显示label后缀
    colon: {
      type: Boolean,
      default: true
    },
    // 是否显示label
    showLabel: {
      type: Boolean,
      default: true
    },
    // 布局
    col: {
      type: Object,
      default: () => {
        return {
          labelCol: { span: 4 },
          wrapperCol: { span: 20 }
        };
      }
    },
    submitLoading: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      labelCol: this.col.labelCol,
      wrapperCol: this.col.wrapperCol,
      form: {},
      replaceFields: {
        children: "children",
        title: "title",
        key: "key"
      }
    };
  },
  computed: {
    // 默认校验规则
    defaultRules() {
      let requireds = this.data.filter(i => i.required);
      let res = {};
      requireds.forEach(item => {
        res[item.prop] = [
          {
            required: true,
            message: item.errorMsg || `请输入${item.label}`,
            trigger: item.trigger || "change"
          }
        ];
      });
      return res;
    }
  },
  watch: {
    value(n) {
      this.form = n;
    },
    // 更新labelCol,wrapperCol
    col() {
      this.labelCol = this.col.labelCol;
      this.wrapperCol = this.col.wrapperCol;
    }
  },
  methods: {
    pressEnter() {
      this.$emit("pressEnter");
    },
    cascaderChange(value, selectedOptions) {
      console.log(value, selectedOptions);
    },
    selectChange(value, option, prop) {
      console.log(value, option, prop);
      // this.form[prop] = value
    },
    radioChange(e) {
      console.log(e);
    },
    onTreeCheck(checkedKeys) {
      this.form.resourceIds = checkedKeys;
    },
    // 任一表单项被校验后触发
    validate(prop, status, msg) {
      this.$emit("validate", { prop, status, msg });
    },
    // 对部分表单字段进行校验
    validateField(props) {
      this.$refs[this.refs].validateField(props);
    },
    // 对整个表单进行校验
    validated() {
      let _this = this;
      return new Promise((resolve, reject) => {
        _this.$refs[_this.refs].validate(valid => {
          if (valid) {
            resolve();
          } else {
            reject();
          }
        });
      });
    },
    // 重置表单
    resetFields() {
      this.$refs[this.refs].resetFields();
    },
    // 提交
    submit() {
      this.validated().then(() => {
        this.$emit("submit");
      });
    }
  },
  created() {
    this.form = this.value;
  }
};
</script>

<style lang="scss" scoped>
::v-deep .sumbit-btn {
  height: 40px;
}
::v-deep .ant-form-item-label {
  padding-right: 12px;
}
::v-deep .ant-form-item-control-wrapper {
  display: flow-root;
}
::v-deep .ant-form-item-label {
  float: left;
}
</style>
